/*
 * BlitzMaxCompiler.java
 *
 * Created on 30. Januar 2008, 19:39
 *
 */
package de.blitzcoder.collide.engine;

import de.blitzcoder.collide.Config;
import de.blitzcoder.collide.Interface;
import de.blitzcoder.collide.util.OS;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.StringTokenizer;
import javax.swing.JOptionPane;

/**
 *
 * @author blitzcoder
 */
public class BlitzMaxCompiler {

    // BMK Parameters
    private static final String BMK_RUN = "-x";
    private static final String BMK_RELEASE = "-r";
    private static final String BMK_DEBUG = "-d";
    private static final String BMK_BUILDALL = "-a";
    private static final String BMK_OUTPUT = "-o";

    private static boolean isBmkAvailable() {
        return Config.getFileProperty("system.bmk").exists();
    }

    public static void compile(File file, String[] params) {

        if (!isBmkAvailable()) {
            JOptionPane.showMessageDialog(Interface.get(), "Sie müssen den Pfad zum BMK in den Einstellungen angeben.");
            return;
        }

        LinkedList<String> command = new LinkedList<String>();

        // BMK
        command.addLast(Config.getProperty("system.bmk"));
        command.addLast("makeapp");

        // Debug or Release?
        if (Interface.getBuildDebug()) {
            command.addLast(BMK_DEBUG);
        } else {
            command.addLast(BMK_RELEASE);
        }

        // Rebuild all source files?
        if (!Interface.getBuildQuick()) {
            command.addLast(BMK_BUILDALL);
        }

        // GUI-build?
        if (Interface.getBuildGuiApp()) {   // This cannot be a constant because it has
            command.addLast("-t");          // to be added seperatly
            command.addLast("gui");
        }

        // Add other params
        for (String param : params) {
            command.addLast(param);
        }

        // specify output file
        String output = file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - 4); // Cut .bmx
        if (Interface.getBuildDebug()) {
            output += ".debug";
        }
        if (OS.isWindows()) {
            output += ".exe";
        }
        command.addLast(BMK_OUTPUT);
        command.addLast(output);

        // Specify sourcefile name
        command.addLast(file.getAbsolutePath());

        // Add params
        for (int i = 0; i < params.length; i++) {
            if (params[i].equals(BMK_RUN)) {
                StringTokenizer tokenizer = new StringTokenizer(Config.getProperty("bmax.commandline"), " ");
                while (tokenizer.hasMoreTokens()) {
                    command.addLast(tokenizer.nextToken());
                }
                break;
            }
        }

        // Run the process
        String name = file.getName();
        if (Interface.getBuildDebug()) {
            name += " [debug]";
        }
        try {
            RunningProcess process = new RunningProcess(name, command.toArray(new String[]{}));
            process.setBlitzMax(true);
            Interface.getOutput().addDocument(process);

            String procname = file.getName().replace(".bmx", "");
            if (Interface.getBuildDebug()) {
                procname += ".debug";
            }
            if (OS.isWindows()) {
                procname += ".exe";
            }
            final String procname_ = procname;
            process.addKillListener(new RunningProcess.KillListener() {

                public void processKilled() {


                    // Kill on Linux/OSX if bmk doesnt manage to..
                    if (!OS.isWindows()) {
                        try {
                            Runtime.getRuntime().exec(new String[] {"killall","-9",procname_});
                        } catch (IOException ex) {
                            throw new Error(ex);
                        }
                    }

                    // Kill on windows
                    if (OS.isWindows()) {
                        try {
                            Runtime.getRuntime().exec(new String[]{"taskkill", "/IM", procname_, "/f"});
                        } catch (Exception ex) {
                            throw new Error(ex);
                        }
                    }
                }
            });

        } catch (Exception ex) {
            throw new Error(ex);
        }

    }

    public static void compile(File file) {
        compile(file, new String[0]);
    }

    public static void compileAndRun(File file) {
        compile(file, new String[]{BMK_RUN});
    }

    /*
     * This Method parses a CompileError given by the bmk
     * It looks like this:
     * **********************
     * Compile Error: Identifier 'l' not found
     * [/home/blitzcoder/Desktop/DebugTest.bmx;13;26]
     * Build Error: failed to compile /home/blitzcoder/Desktop/DebugTest.bmx
     * **********************
     */
    public static void parseCompileError(String str) {
        String[] lines = str.split("\n");

        String line = lines[1];
        line = line.replace("]", "").replace("[", "");

        int pos = line.indexOf(";");
        String fileName = line.substring(0, pos);
        File file = new File(fileName);
        line = line.substring(pos + 1);

        pos = line.indexOf(";");
        int lineNumber = Integer.parseInt(line.substring(0, pos));

        Interface.selectLineInFile(file, lineNumber);

        JOptionPane.showMessageDialog(Interface.get(), lines[0]);

    }
}
